﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection;
using PineLake.Drmwe.SystemConfig;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Http;

namespace PineLake.Drmwe.Core.JWT
{
    /// <summary>
    /// JWT鉴权 注入服务
    /// </summary>
    public static class JwtAuthenticationStartup
    {
        /// <summary>
        /// JWT鉴权
        /// </summary>
        /// <param name="services">JWT鉴权服务</param>
        /// <returns></returns>
        public static IServiceCollection AddJwtAuthenticationStartup(this IServiceCollection services)
        {
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(option =>
                    {
                        option.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuerSigningKey = true,
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppSettings.AuthenKey)),//密钥
                            ValidateIssuer = true,
                            ValidIssuer = AppSettings.AuthenIssuer,//颁发Token的web应用程序地址(当前程序)
                            ValidateAudience = true,
                            ValidAudience = AppSettings.AuthenAudience,//token接收程序的地址(WebApi)
                            ValidateLifetime = true,
                            ClockSkew = TimeSpan.FromMinutes(double.Parse(AppSettings.AuthenClockSkew))//ClockSkew默认值为5分钟，它是一个缓冲期，例如Token设置有效期为30分钟 过期时间35分钟
                        };
                        option.Events = new JwtBearerEvents
                        {
                            // 此处为ToKen验证失败后触发的事件
                            OnChallenge = Context =>
                            {
                                // 此处代码为终止.Net Core 默认的返回类型和数据结果，这个很重要哦，必须
                                Context.HandleResponse();
                                // 自定义返回的数据结果         
                                var Payload = JsonConvert.SerializeObject(new { StatusCode = StatusCodes.Status401Unauthorized, Info = "令牌无效!", Data = new { Content = "令牌无效,请检查获取令牌,或者重新获取令牌!" } });
                                // 自定义返回的数据类型
                                Context.Response.ContentType = "application/json";
                                // 自定义返回状态码，默认为 401 
                                Context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                                // 输出 Json 数据结果
                                Context.Response.WriteAsync(Payload);
                                return Task.FromResult(0);
                            }
                        };
                    });
            return services;
        }
    }
}
